package cn.jbt.api.admin.advice;

import cn.dev33.satoken.stp.StpUtil;
import cn.jbt.api.admin.annotation.Log;
import cn.jbt.api.admin.entity.SysLog;
import cn.jbt.api.admin.filter.LoginInfoAccessContext;
import cn.jbt.api.admin.repository.SysLogRepository;
import cn.jbt.util.IpAddressUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONException;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.util.Date;

@Aspect
@Component
@Slf4j
public class LogAdvice {

    @Resource
    private SysLogRepository sysLogRepository;
    @Resource
    private HttpServletRequest httpServletRequest;

    public LogAdvice() {
    }

    @Around(value = "@annotation(cn.jbt.api.admin.annotation.Log)")
    public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Log logAnnotitaon = methodSignature.getMethod().getDeclaredAnnotation(Log.class);

        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();

        SysLog sysLog = new SysLog();
        sysLog.setMethodName(String.format("%s.%s()", className, methodName));
        sysLog.setBizType(logAnnotitaon.bizType());
        sysLog.setBizName(logAnnotitaon.bizName());
        sysLog.setReqUrl(httpServletRequest.getRequestURI());
        sysLog.setReqMethod(httpServletRequest.getMethod());
        sysLog.setIpAddr(IpAddressUtil.getIp(httpServletRequest));
        sysLog.setUa(httpServletRequest.getHeader("User-Agent"));
        sysLog.setStatus(1);
        sysLog.setRelativeId(logAnnotitaon.relativeId());
        sysLog.setCreateTime(new Date());

        // 操作人员
        if (StpUtil.isLogin()) {
            sysLog.setUsername(LoginInfoAccessContext.getLoginInfo().getUsername());
        }

        String args = "";
        try {
            // 请求参数
            args = JSON.toJSONString(joinPoint.getArgs());
        } catch (Exception ignored) {

        }
        if (StringUtils.isNotEmpty(args)) {
            sysLog.setReqBody(args.length() > 10000 ? args.substring(10000) : args);
        }

        Object proceed = null;
        try {
            proceed = joinPoint.proceed();
            // 返回参数
            String result = JSON.toJSONString(proceed);
            if (StringUtils.isNotEmpty(result)) {
                sysLog.setResBody(result.length() > 10000 ? result.substring(10000) : result);
            }

            sysLogRepository.save(sysLog);
            return proceed;
        } catch (JSONException e) {
            sysLogRepository.save(sysLog);
            return proceed;
        } catch (Exception e) {
            sysLog.setStatus(0);
            if (StringUtils.isNotEmpty(e.getMessage())) {
                sysLog.setErrorMsg(e.getMessage().length() > 4000 ? e.getMessage().substring(4000) : e.getMessage());
            }
            sysLogRepository.save(sysLog);
            throw e;
        }
    }

}
